package com.onesports.intelligent.k12.polarlight.service.campus;

import com.onesports.intelligent.k12.polarlight.constant.RedisKeyConstant;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.onesports.intelligent.k12.polarlight.domain.entity.organization.Coach;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.CoachCampusRel;
import com.onesports.intelligent.k12.polarlight.mapper.organization.CoachMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.onesports.framework.kit.common.util.ParamUtils;
import com.onesports.intelligent.k12.polarlight.common.errors.exceptions.BusinessException;
import com.onesports.intelligent.k12.polarlight.domain.dto.common.UpdateStatesDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.operation.OperationCampusCourseDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.operation.PageOperationCampusDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.organization.CampusSearchDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.organization.InsertOrganizationCampusDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.organization.PageOrganizationCampusDTO;
import com.onesports.intelligent.k12.polarlight.domain.dto.organization.UpdateOrganizationCampusDTO;
import com.onesports.intelligent.k12.polarlight.domain.entity.market.Product;
import com.onesports.intelligent.k12.polarlight.domain.entity.organization.OrganizationCampus;
import com.onesports.intelligent.k12.polarlight.domain.entity.sys.Area;
import com.onesports.intelligent.k12.polarlight.domain.vo.common.CanChoiceDataVO;
import com.onesports.intelligent.k12.polarlight.domain.vo.course.CourseScheduleDetailVO;
import com.onesports.intelligent.k12.polarlight.domain.vo.operation.PageOperationCampusVO;
import com.onesports.intelligent.k12.polarlight.domain.vo.organization.CampusSearchVO;
import com.onesports.intelligent.k12.polarlight.domain.vo.organization.PageOrganizationCampusVO;
import com.onesports.intelligent.k12.polarlight.mapper.course.ClassInfoMapper;
import com.onesports.intelligent.k12.polarlight.mapper.market.ProductCampusRelMapper;
import com.onesports.intelligent.k12.polarlight.mapper.market.ProductMapper;
import com.onesports.intelligent.k12.polarlight.mapper.organization.CoachCampusRelMapper;
import com.onesports.intelligent.k12.polarlight.mapper.organization.OrganizationCampusMapper;
import com.onesports.intelligent.k12.polarlight.mapper.sys.AreaMapper;
import com.onesports.intelligent.k12.polarlight.security.SecurityUtils;
import com.onesports.intelligent.k12.polarlight.service.course.CourseScheduleService;
import com.onesports.intelligent.k12.polarlight.service.course.CourseService;
import com.onesports.intelligent.k12.polarlight.util.BeanCopyUtil;
import com.onesports.intelligent.k12.polarlight.util.GouldUtil;
import com.onesports.intelligent.k12.polarlight.util.RedisUtils;

import io.jsonwebtoken.lang.Collections;

/**
 * @author wangcx
 **/
@Service
public class OrganizationCampusService extends ServiceImpl<OrganizationCampusMapper, OrganizationCampus> {
    @Resource
    private OrganizationCampusMapper mapper;
    @Resource
    private CoachCampusRelMapper coachCampusRelMapper;
    @Resource
    private ClassInfoMapper classInfoMapper;
    @Resource
    private ProductCampusRelMapper productCampusRelMapper;
    @Resource
    private ProductMapper productMapper;
    @Resource
    @Lazy
    private CourseService courseService;
    @Resource
    private AreaMapper areaMapper;
    @Resource
    private OrganizationCampusMapper organizationCampusMapper;
    @Resource
    private CourseScheduleService courseScheduleService;

    @Resource
    private RedisUtils redisUtils;
    @Resource
    private CoachMapper coachMapper;

    /**
     * 获取校区下拉列表
     *
     * @param campusName 校区名称
     * @param status     是否包含不可用校区
     * @return List<CanChoiceDataVO>
     */
    public List<CanChoiceDataVO> dropDown(String campusName, Boolean status) {
//        new LambdaQueryWrapper<OrganizationCampus>()
//                .like(ParamUtils.isNotEmpty(campusName), OrganizationCampus::getCampusName, campusName)
//                .eq(ParamUtils.isNotEmpty(status) && status.equals(Boolean.TRUE), OrganizationCampus::getStatus, status)
        List<OrganizationCampus> list = this.mapper.selectCampus(campusName, status);

        if (ParamUtils.isEmpty(list)) {
            return new ArrayList<>();
        }
        return list.stream().map(i -> CanChoiceDataVO.builder().id(i.getId()).name(i.getCampusName()).build()).collect(Collectors.toList());

    }

    /**
     * 校区搜索列表
     *
     * @param dto
     * @return
     * @throws JsonProcessingException
     */
    public List<CampusSearchVO> getCampusSearchList(CampusSearchDTO dto) throws JsonProcessingException {

        String startLngLat = dto.getLng() + "," + dto.getLat();
        // 查询校区
        List<CampusSearchVO> list = mapper.getCampusSearchList(dto);
        if (ParamUtils.isEmpty(list)) {
            throw new BusinessException("暂无数据！");
        }
        //查询所有区域
        List<Area> areaList = areaMapper.selectList(null);
        Map<String, Area> areaMap = areaList.stream().collect(Collectors.toMap(Area::getRegionCode, area -> area));
        for (CampusSearchVO campusSearchVO : list) {
            String endLngLat = campusSearchVO.getLng() + "," + campusSearchVO.getLat();
            if (redisUtils.exists(RedisKeyConstant.campus_map.getKey() + endLngLat)) {
                String distance1 = redisUtils.get(RedisKeyConstant.campus_map.getKey() + endLngLat);
                campusSearchVO.setDistance(Long.valueOf(distance1));
            } else {
                // 根据经度和维度计算距离
                Long distance = GouldUtil.getDistance(startLngLat, endLngLat);
                campusSearchVO.setDistance(distance);
                redisUtils.set(RedisKeyConstant.campus_map.getKey() + endLngLat, Long.toString(distance));
            }
            Area area = areaMap.get(campusSearchVO.getArea());
            if (ParamUtils.isNotEmpty(area)) {
                campusSearchVO.setAreaName(area.getRegionName());
            }

        }
        // 升序
        return list.stream().sorted(Comparator.comparing(CampusSearchVO::getDistance)).collect(Collectors.toList());
    }

    /**
     * 运营端分页查询校区列表
     *
     * @param page 分页参数
     * @param dto  入参
     * @return page1
     */
    public IPage<PageOperationCampusVO> findPage(Page<PageOperationCampusVO> page, PageOperationCampusDTO dto) {
        IPage<PageOperationCampusVO> page1 = this.mapper.findPage(page, dto);
        for (int i = 0; i < page1.getRecords().size(); i++) {
            // 查询学生数量
            Long studentNumber = classInfoMapper.selectStudentNumber(page1.getRecords().get(i).getCampusId());
            page1.getRecords().get(i).setStudentNumber(studentNumber != null ? studentNumber : 0L);

            // 查询教练数量
            Long coachNumber = coachCampusRelMapper.selectCoachNumber(page1.getRecords().get(i).getCampusId());
            page1.getRecords().get(i).setCoachNumber(coachNumber != null ? coachNumber : 0L);
        }

        return page1;
    }

    public List<OrganizationCampus> listByOrganizationId(String organizationId) {
        LambdaQueryWrapper<OrganizationCampus> wrapper = new LambdaQueryWrapper<OrganizationCampus>()
                .eq(OrganizationCampus::getDeleted, false)
                .eq(OrganizationCampus::getOrganizationId, organizationId);
        return baseMapper.selectList(wrapper);
    }

    /**
     * 机构端分页查询校区列表
     *
     * @param page 分页参数
     * @param dto  入参
     * @return
     */
    public IPage<PageOrganizationCampusVO> selectOrganizationPage(Page<PageOrganizationCampusDTO> page,
                                                                  PageOrganizationCampusDTO dto) {
        dto.setOrganizationId(SecurityUtils.getOrganizationId());
        return this.mapper.selectOrganizationPage(page, dto);
    }

    /**
     * 新增或修改时检查同一机构下校区名称是否存在
     *
     * @param id         校区id
     * @param campusName 校区名称
     */
    private void checkCampusName(String id, String campusName, String organizationId) {
        Long count = this.mapper.selectCount(new LambdaQueryWrapper<OrganizationCampus>()
                .eq(OrganizationCampus::getDeleted, false)
                .eq(OrganizationCampus::getOrganizationId, organizationId)
                .ne(StringUtils.isNotEmpty(id), OrganizationCampus::getId, id)
                .eq(OrganizationCampus::getCampusName, campusName));
        if (count > 0) {
            throw new BusinessException("校区名称已存在");
        }

    }

    /**
     * 新增校区
     *
     * @param dto 入参
     */
    public void add(InsertOrganizationCampusDTO dto) {
        checkCampusName(null, dto.getCampusName(), dto.getOrganizationId());
        String organizationId = SecurityUtils.getOrganizationId();
        dto.setOrganizationId(organizationId);
        OrganizationCampus entity = new OrganizationCampus();
        BeanCopyUtil.copyProperties(dto, entity);
        this.mapper.insert(entity);
        courseService.initCourseSellPrice(entity.getId(), organizationId);
    }

    /**
     * 修改校区资料
     *
     * @param dto 入参
     */
    public void upd(UpdateOrganizationCampusDTO dto) {
        List<String> campusIds = new ArrayList<>();
        campusIds.add(dto.getId());
        dto.setOrganizationId(SecurityUtils.getOrganizationId());
        checkCampusName(dto.getId(), dto.getCampusName(), dto.getOrganizationId());
        OrganizationCampus entity = new OrganizationCampus();
        BeanCopyUtil.copyProperties(dto, entity);
        this.mapper.updateById(entity);
        // 判断分账比例是否大于100
        this.whetherExceedSubRatio(null,campusIds);
    }

    /**
     * function: 判断分账比例是否大于100
     *
     * @param coachId 教练id
     * @param campusIds 校区id
     * @author WangCX
     * @since 2022/8/12 21:16
     */
    public void whetherExceedSubRatio(String coachId, List<String> campusIds) {
        Integer flag = this.coachMapper.whetherExceedSubRatio(coachId, campusIds);
        if (ParamUtils.isNotEmpty(flag) && flag == 1) {
            throw new BusinessException("校区和教练分账比例不可以大于100！");
        }
    }

    /**
     * 启用禁用校区
     * 启用 课程商品上架
     * 禁用 有课程商品不可禁用
     *
     * @param dto 入参
     */
    public void updStatus(UpdateStatesDTO dto) {
        List<String> productIds = productCampusRelMapper.selectIdsByCampusId(dto.getId());
        if (!Collections.isEmpty(productIds)) {
            if (!dto.getStatus()) {
                Long aLong = this.productMapper.selectCount(new LambdaQueryWrapper<Product>()
                        .in(Product::getId, productIds).eq(Product::getSell, true));
                if (aLong > 0) {
                    throw new BusinessException("存在已上架的商品，不可以禁用！");
                }
            } else {
                LambdaUpdateWrapper<Product> lam = new LambdaUpdateWrapper<>();
                lam.eq(Product::getDeleted, false)
                        .set(Product::getSell, true);
                lam.in(Product::getId, productIds);
                productMapper.update(null, lam);
            }

        }
        OrganizationCampus entity = new OrganizationCampus();
        BeanCopyUtil.copyProperties(dto, entity);
        this.mapper.updateById(entity);

    }


    /**
     * 获取校区
     *
     * @return
     */

    public List<CampusSearchVO> getCampusList() {

        return organizationCampusMapper.getCampusList();
    }

    /**
     * 根据区域code获取校区相关数据
     *
     * @param areaCode
     * @return
     */
    public List<CampusSearchVO> getAreaCampusList(String areaCode) {
        return organizationCampusMapper.getAreaCampusList(areaCode);
    }

    /**
     * 查看排课表
     *
     * @param dto 入参
     * @return CourseScheduleDetailVO
     */
    public List<CourseScheduleDetailVO> getCourse(OperationCampusCourseDTO dto) {
        List<String> campusIds = new ArrayList<>();
        campusIds.add(dto.getCampusId());
        return courseScheduleService.schedulePreview(dto.getScheduleId(), campusIds,
                dto.getCourseId(), dto.getStartTime(), dto.getEndTime(), null);
    }

    /**
     * 拼班成功 拼班数量加一
     *
     * @param campusId 校区Id
     */
    public void addCampusSpellNum(String campusId) {
        OrganizationCampus oc = this.getById(campusId);
        oc.setClassNum(oc.getClassNum() + 1);
        this.updateById(oc);

    }
}
